package com.zzg.demo.laboratory.threadpool;

import lombok.SneakyThrows;

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestThreadPoolUseSynchronousQueue {
    private static ThreadPoolExecutor getThreadPoolExecutor(int corePoolSize, int maximumPoolSize) {
        return new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                0L,
                TimeUnit.MILLISECONDS,
                new SynchronousQueue<>(),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy() // 当任务被拒绝时在调用者线程中运行任务
        );
    }

    @SneakyThrows
    public static void print(){
        System.out.println(LocalDateTime.now() + "-" + "Hello World：" + Thread.currentThread().getName());
        Thread.sleep(10000);
    }

    /**
     * 使用SynchronousQueue作为线程池的队列时，因为这个队列的特性，当提交的任务超过核心线程数时，队列并不会暂存任务，而是直接触发创建新的线程去运行剩下的任务（超过最大线程数会触发拒绝策略）。
     * 相当于这个队列只是一个中转站，没有暂存的作用，所以虽然它是个无界队列，但是并不会造成内存溢出的问题
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(LocalDateTime.now() + "-" + "start");
        ThreadPoolExecutor threadPoolExecutor = getThreadPoolExecutor(2, 10);
        for(int i = 0; i < 20; i++){
            threadPoolExecutor.execute(TestThreadPoolUseSynchronousQueue::print);
        }
        threadPoolExecutor.shutdown();
        System.out.println(LocalDateTime.now() + "-" + "end");
    }
}
